package libs

import (
	"archive/zip"
	"bytes"
	"fmt"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/encoding/unicode"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"unicode/utf8"
)

// UnzipFile 分页解压(源文件中存在的子目录,将子目录中的文件全部目标文件中)
// @param: src-源文件
// @param: destDir-目标文件夹
// @param: isChild-保留子文件夹 默认保留
func UnzipFile(src, destDir string, isChild bool) (err error) {
	zip, err := zip.OpenReader(src)
	if err != nil {
		return fmt.Errorf("打开zip文件失败：%w", err)
	}
	for _, f := range zip.File {
		var decodeName string
		if f.Flags == 0 {
			////如果标致位是0  则是默认的本地编码   默认为gbk
			i := bytes.NewReader([]byte(f.Name))
			content, err := ioutil.ReadAll(i)
			if err != nil {
				return fmt.Errorf("读取异常：%w", err)
			}
			decodeName, err = detectAndConvertCharset(content)
			if err != nil {
				return fmt.Errorf("转码异常：%w", err)
			}
		} else {
			//如果标志为是 1 << 11也就是 2048  则是utf-8编码
			decodeName = f.Name
		}

		fpath := filepath.FromSlash(filepath.Join(destDir, decodeName))

		if isChild { //不保留子文件夹
			fpath = filepath.FromSlash(filepath.Join(destDir, filepath.Base(decodeName)))
		}

		if f.FileInfo().IsDir() {
			if !isChild {
				os.MkdirAll(fpath, os.ModePerm)
				os.Chmod(fpath, f.Mode()) // 立即关闭文件夹
			}
		} else {
			if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
				return err
			}
			inFile, err := f.Open()
			if err != nil {
				return fmt.Errorf("failed to open file in zip: %w", err)
			}
			defer inFile.Close()
			dir := filepath.Dir(fpath)
			name := filepath.Base(fpath)
			//统一文件名全改成大写
			newFpath := filepath.Join(dir, strings.ToUpper(name))
			outFile, err := os.OpenFile(newFpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
			if err != nil {
				return fmt.Errorf("failed to create file: %w", err)
			}
			defer outFile.Close()
			_, err = io.Copy(outFile, inFile)
			if err != nil {
				return fmt.Errorf("failed to copy file contents: %w", err)
			}
		}

	}

	return err
}

// detectAndConvertCharset 转码
func detectAndConvertCharset(data []byte) (string, error) {
	// 尝试 UTF-8 解码
	if utf8.Valid(data) {
		return string(data), nil
	}
	// 尝试 GB18030 解码
	if decoder := simplifiedchinese.GB18030.NewDecoder(); decoder != nil {
		if decoded, err := decoder.Bytes(data); err == nil {
			return string(decoded), nil
		}
	}

	// 尝试 UTF-16 解码
	if decoder := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewDecoder(); decoder != nil {
		if decoded, err := decoder.Bytes(data); err == nil {
			return string(decoded), nil
		}
	}

	// 如果以上都不成功，则返回原始字节串
	return string(data), nil
}
